package com.iamk.semanticsegment;

import java.awt.image.BufferedImage;
import java.util.ArrayList;

import com.iamk.util.GetData;
import com.iamk.util.ImageUtil;

public class ColorFeature {

	double[][] listVij;
	double[][] listEij;
	ArrayList<Pixel> colorFeatures;
	BufferedImage imgOriginal;

	public ColorFeature(BufferedImage imgOriginal) {
		this.imgOriginal = imgOriginal;
		colorFeatures = new ArrayList<Pixel>();
		listVij = new double[3][imgOriginal.getWidth()* imgOriginal.getHeight()];
		listEij = new double[3][imgOriginal.getWidth()* imgOriginal.getHeight()];
	}

	public void run() {
		// Convert to CIELABlong
		BufferedImage imgCIELAB = AccurateLAB.getLABImage(imgOriginal);
		// Get 3 channel of Image
		int width = imgCIELAB.getWidth();
		int height = imgCIELAB.getHeight();
		double[][] channelL = new double[width][height];
		double[][] channela = new double[width][height];
		double[][] channelb = new double[width][height];

		for (int i = 0; i < height; i++) {
			for (int j = 0; j < width; j++) {
				int Lab = imgCIELAB.getRGB(j, i);
				int L = Lab >> 16 & 0xff;
				int a = Lab >> 8 & 0xff;
				int b = Lab & 0xff;
				channelL[j][i] = L;
				channela[j][i] = a;
				channelb[j][i] = b;
			}
		}
		// Apply Sobel for each channel
		SobelOperator sobelOp = new SobelOperator();
		double[][] magnitudeL = sobelOp.filter(channelL);
		double[][] magnitudea = sobelOp.filter(channela);
		double[][] magnitudeb = sobelOp.filter(channelb);

		for (int i = 0; i < height; i++) {
			for (int j = 0; j < width; j++) {
				// Construct local image window
				ImageWindow window = new ImageWindow(5, i, j);
				// Compute standard deviation of each channel
				window.getValueImageWindow(channelL);
				listVij[0][i * width + j] = window.getStandardDeviation(channelL);

				window.getValueImageWindow(channela);
				listVij[1][i * width + j] = window.getStandardDeviation(channela);

				window.getValueImageWindow(channelb);
				listVij[2][i * width + j] = window.getStandardDeviation(channelb);
				// Compute discountinuity of each channel
				listEij[0][i * width + j] = magnitudeL[j][i];
				listEij[1][i * width + j] = magnitudea[j][i];
				listEij[2][i * width + j] = magnitudeb[j][i];
			}
		}
		// Normalization Vij
		double maxVijL = getMax(GetData.getRowMatrix(listVij, 0));
		double maxVija = getMax(GetData.getRowMatrix(listVij, 1));
		double maxVijb = getMax(GetData.getRowMatrix(listVij, 2));

		for (int i = 0; i < listVij[0].length; i++) {
			listVij[0][i] /= maxVijL;
			listVij[1][i] /= maxVija;
			listVij[2][i] /= maxVijb;
		}
		// Normalization Eij
		double maxEijL = getMax(GetData.getRowMatrix(listEij, 0));
		double maxEija = getMax(GetData.getRowMatrix(listEij, 1));
		double maxEijb = getMax(GetData.getRowMatrix(listEij, 2));

		for (int i = 0; i < listEij[0].length; i++) {
			listEij[0][i] /= maxEijL;
			listEij[1][i] /= maxEija;
			listEij[2][i] /= maxEijb;
		}
		// Compute color feature
		for (int i = 0; i < height; i++) {
			for (int j = 0; j < width; j++) {
				// Create pixel [i,j,feature]
				Pixel p = new Pixel();
				p.x = i;
				p.y = j;
				p.features = new double[3];
				p.features[0] = 1 - listEij[0][i * width + j]* listVij[0][i * width + j];
				p.features[1] = 1 - listEij[1][i * width + j]* listVij[1][i * width + j];
				p.features[2] = 1 - listEij[2][i * width + j]* listVij[2][i * width + j];

				colorFeatures.add(p);
			}
		}
	}

	public double getMax(double[] mListIdx) {
		double max = -1;
		for (int i = 0; i < mListIdx.length; i++) {
			if (max < mListIdx[i])
				max = mListIdx[i];
		}
		return max;
	}

	public static void main(String[] args) {
		BufferedImage img = ImageUtil.readImage("lena.bmp");
		ColorFeature cf = new ColorFeature(img);
		cf.run();
		 for(Pixel p:cf.colorFeatures){
		 for(double i:p.features){
		 System.out.print(i + ", ");
		 }
		 System.out.println();
		 }
	}
}
